#ifndef RAYTRACE_H
#define RAYTRACE_H

/**
 * XXX: DO NOT MODIFY THIS FILE.
 */

// This enum specifies which type of allocation to use.
typedef enum PartType {
  PART_STATIC_STRIPS,
  PART_STATIC_BLOCKS,
  PART_STATIC_CYCLES,
  PART_DYNAMIC,
} PartType;

/**
 * This struct contains configuration information needed by the master and
 * slaves
 */
typedef struct ConfigData {
  unsigned int height;    // How many pixels high to make the rendered image.
  unsigned int width;     // How many pixels wide to make the rendered image.

  int mpi_procs;          // The number of MPI processes.
  int mpi_rank;           // This process' MPI rank.

  PartType part_mode;     // Partition mode to use.

  int block_width;        // Used for dynamic allocation.
  int block_height;       // Used for dynamic allocation.

  int strip_height;       // Used for cyclical allocation.

  // User programs should not touch this field.
  struct Scene *the_scene;// The scene to render.
} ConfigData;

/**
 * Name: initialize
 *
 * Description:
 * Initializes the raytracing program. This function calls MPI_Init to
 * initialize MPI, parsse command line arguments to extract configuration
 * information, and loads the scene specified on the command line.
 *
 * Parameters:
 * @param argc      the number of command line arguments
 * @param argv      the command line arguments
 * @param data      where to store configuration data
 *
 * Returns:
 * @return int      0 on error, nonzero otherwise
 */
int initialize( int *argc, char ***argv, ConfigData *data );

/**
 * Name: shutdown
 *
 * Description:
 * This function cleans up memory allocated within the initialize() function.
 * This function calls the MPI_Finalize() function and frees memory used to
 * store the scene.
 *
 * Parameters:
 * @param data      configuration data containing information about what to free
 */
void shutdown( ConfigData *data );

/**
 * Name: shadePixel
 *
 * Description:
 * Ray traces a single pixel of a scene. The pixel to trace is specified by the
 * given `x' and `y' coordinates, where (0,0) is the top left of the image.
 *
 * The calculated color will be stored at the given location. The location must
 * have space for three values: a red, a green, and a blue color component.
 * These color values will always been in the range [0.0, 1.0].
 *
 * Parameters:
 * @param color         where to store the calculated color
 * @param x             x coordinate of pixel to render
 * @param y             y coordinate of pixel to render
 * @param data          configuration data
 */
void shadePixel( float *color, int x, int y, ConfigData *data );

/**
 * Name: getRenderName
 *
 * Description:
 * Generates a filename to use for a rendering based on the current system time.
 *
 * The name generated by this function is dependent on the system time, so do
 * not expect multiple calls to this function to return the same value.
 *
 * The caller is responsible for free(3)ing the string returned by this
 * function.
 *
 * The render name will always be prefixed with 'renders/'.
 *
 * Returns:
 * @return char*    the filename to use (including directory)
 */
char *getRenderName();

/**
 * Name: savePixels
 *
 * Description:
 * Saves the pixel data stored within 'pixels' to a png file. The pixel data is
 * expected to order data such that the first width * 3 elements in the array
 * are the top row of the image, the next width * 3 elements the second to top
 * row, and so on. The pixel data is also expected to occur in RGB triplets,
 * e.g. pixels[0], pixels[1], and pixels[2] represents the RGB values of the
 * top left pixel in the resulting image.
 *
 * 'pixels' must contain at least (width * height * 3) elements.
 *
 * Parameters:
 * @param filename      name to use for saved file
 * @param pixels        the pixel data to save
 * @param width         how wide the image is
 * @param height        how tall the image is
 *
 * Returns:
 * @return short        0 if an error occured, 1 otherwise
 */
short savePixels( char const *filename, float const *pixels,
                  unsigned int width, unsigned int height );

#endif
